package main

import (
	"bytes"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
	"time"
)

type Alarm struct {
	AlarmName     string `json:"alarm_name"`
	AlarmID       string `json:"alarm_id"`
	Flag          string `json:"flag"`
	RefreshedTime int64  `json:"refreshed_time"`
	TID           string `json:"t_id"`
	TimeChanged   string `json:"time_changed"`
	ThingName     string `json:"thing_name"`
	Level         int    `json:"level"`
}

type Login struct {
	UserName string `json:"un"`
	Password string `json:"pd"`
}

func (pLogin *Login) init() {

	bP := sha256.Sum256([]byte(pLogin.Password))
	pLogin.Password = hex.EncodeToString(bP[:])
}

func alarmToString(alarm Alarm) string {
	res := fmt.Sprintf("设备%s(id:%s)于%s发生%s告警", alarm.ThingName, alarm.TID, alarm.TimeChanged, alarm.AlarmName)
	return res
}

type MsgContect struct {
	Content string `json:"content"`
}

type MSGT struct {
	MsgType string     `json:"msgtype"`
	Text    MsgContect `json:"text"`
}

type AlarmResult struct {
	Result []Alarm `json:"result"`
}
type ctrlCmd struct {
	ID    string `json:"identifier"`
	Index int    `json:"index"`
	TID   string `json:"tid"`
}

func createMsg(msgText string) MSGT {
	now := time.Now()
	msg := MSGT{
		MsgType: "text",
		Text: MsgContect{
			Content: "运维@" + now.Format("2006-01-02 15:04:05") + ":" + msgText,
		},
	}
	return msg
}

const dingURL = "https://oapi.dingtalk.com/robot/send?access_token=f1d9896cc45d17c602b5d23717ef7a6183201f4c002752319d7de90bffd08698"

func sendDingDingMsg(msg string) {
	buff, _ := json.Marshal(createMsg(msg))
	if buff != nil {
		req, _ := http.NewRequest("POST", dingURL, bytes.NewBuffer(buff))
		req.Header.Set("Content-Type", "application/json")
		client := &http.Client{}
		client.Do(req)
	}

}

func ctrl(uid string, pid string, ctrlUri string) error {
	cmd := ctrlCmd{
		ID:  pid,
		TID: uid,
	}
	buf, _ := json.Marshal(&cmd)
	req, _ := http.NewRequest("PUT", ctrlUri, bytes.NewBuffer(buf))
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Cookie", cookie)
	client := &http.Client{}
	resp, err := client.Do(req)
	fmt.Println("**********begin*******", err)
	if err == nil {
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		if err == nil {
			var mapResult map[string]interface{}
			err = json.Unmarshal(body, &mapResult)
			re, ok := mapResult["result"]

			fmt.Println("**********result*1******", re, ok, err)
			if ok {
				result, rok := re.(map[string]interface{})
				if rok {
					resulti, roki := result["result"]
					if roki {
						result, rok = resulti.(map[string]interface{})
						if rok {
							endv, endok := result["end"]
							fmt.Println("**********end*******", result, endv, endok)
							if endok {
								fmt.Println("**********11111*******", endok, endv)
								return nil
							}
							return errors.New("end not found")
						}

					}
					return errors.New("result not found")

				}
				return errors.New("result not found")
			}
			return errors.New("no result found")
		}
	}
	return err
}

func filterFun(devID string, alarmId string) bool {
	return strings.Contains(devID, "16baf3ae614a@edge") && strings.Contains(alarmId, "offline")
}

func makeFun(devID string) func(string, string) bool {
	return func(targetID string, alarmId string) bool {
		return strings.Contains(targetID, devID) && strings.Contains(alarmId, "offline")
	}
}

func checkCtrl(tid string, pid string, url string) {
	err := ctrl(tid, pid, url)
	if err != nil {
		sendDingDingMsg("控制失败，请检查消息队列或设备状态")
	}
}

var cookie string

func getAlarms(loginUrl string, alarmUrl string, userName string, password string, filterFun func(devID string, alarmId string) bool) {

	pLogin := &Login{
		UserName: userName,
		Password: password,
	}
	pLogin.init()
	buf, _ := json.Marshal(pLogin)
	req, err := http.NewRequest("POST", loginUrl, bytes.NewBuffer(buf))
	if err != nil {
		sendDingDingMsg("错误1：" + err.Error())
		return
	}
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}

	resp, err := client.Do(req)
	if err == nil {
		defer resp.Body.Close()

		reqAlarm, errAlarm := http.NewRequest("GET", alarmUrl, nil)
		if errAlarm == nil {
			cookie = resp.Header.Get("Set-Cookie")
			reqAlarm.Header.Set("Cookie", cookie)
			resp, err := client.Do(reqAlarm)
			if err == nil {
				defer resp.Body.Close()
				body, err := ioutil.ReadAll(resp.Body)
				//fmt.Println("get data-------", len(body), body, err, resp.StatusCode)
				if err != nil || resp.StatusCode == 401 {
					serr := ""
					if err != nil {
						serr = err.Error()
					} else {
						serr = "401登录失败"
					}
					sendDingDingMsg("错误3：" + serr)
					return
				}
				var result AlarmResult
				//var alarms []Alarm
				err = json.Unmarshal(body, &result)
				if err != nil {
					sendDingDingMsg("错误2：" + err.Error())
					return
				}
				isFound := false

				for _, alarm := range result.Result {
					if filterFun(alarm.TID, alarm.AlarmID) {
						display := alarmToString(alarm)
						sendDingDingMsg(display)
						isFound = true
					}

				}
				if !isFound {
					sendDingDingMsg("检查未见异常")
				}
			}

		}

	}

}

func main() {
	getAlarms("http://42.192.199.243:18866/api/su/login", "http://42.192.199.243:18866/api/alarm/real",
		"IOT2021", "Mima2021@)@!", makeFun("16baf3ae614a@edge1"))
	checkCtrl("WuAqsd0ELR77GnUyA_4qR", "heat", "http://42.192.199.243:18866/api/service/?uid=a")
}
